package com.example.task.service.impl;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.task.entity.TaskInfo;
import com.example.task.service.TaskService;

@Service("taskService")
public class TaskServiceImpl implements TaskService {

	DateTimeFormatter formatter = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss");

	private Logger logger = LoggerFactory.getLogger(TaskServiceImpl.class);

	@Autowired
	private Scheduler scheduler;

	@Override
	public List<TaskInfo> list() {
		List<TaskInfo> list = new ArrayList<>();
		try {
			for (String groupJob : scheduler.getJobGroupNames()) {
				for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.<JobKey>groupEquals(groupJob))) {
					List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
					for (Trigger trigger : triggers) {
						Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
						JobDetail jobDetail = scheduler.getJobDetail(jobKey);
						String cronExpression = "", createTime = "";

						if (trigger instanceof CronTrigger) {
							CronTrigger cronTrigger = (CronTrigger) trigger;
							cronExpression = cronTrigger.getCronExpression();
							createTime = cronTrigger.getDescription();
							
						}
						TaskInfo info = new TaskInfo();
						info.setTaskName(jobKey.getName());
						info.setGroup(jobKey.getGroup());
						info.setDesc(jobDetail.getDescription());
						info.setStatus(triggerState.name());
						info.setCronExpression(cronExpression);
						info.setCreateTime(createTime);
						info.setExeclazz(jobDetail.getJobClass().getName());
						list.add(info);
					}
				}
			}
		} catch (SchedulerException e) {
			e.printStackTrace();
		}

		return list;
	}

	@Override
	public void addJob(TaskInfo info) {
		
		String jobName = info.getTaskName(),
			jobId=info.getJobId(),
				jobGroup = info.getGroup(), 
				cronExpression = info.getCronExpression(),
				jobDescription = info.getDesc(), 
				createTime = LocalDateTime.now().format(formatter),
				execlazz=info.getExeclazz();
		try {
			if (checkExists(jobName, jobGroup)) {
				logger.info("add job fail, job already exist, jobGroup:{}, jobName:{}", jobGroup, jobName);
			}
			if(jobId==null) {
				jobId=UUID.randomUUID().toString();
			}
			TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
			JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
			
			CronScheduleBuilder schedBuilder = CronScheduleBuilder.cronSchedule(cronExpression)
					.withMisfireHandlingInstructionDoNothing();
			CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withDescription(createTime)
					.withSchedule(schedBuilder).build();

			Class<? extends Job> clazz = (Class<? extends Job>) Class.forName(execlazz);
			JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(jobKey).withDescription(jobDescription).build();
			scheduler.scheduleJob(jobDetail, trigger);
		} catch (SchedulerException | ClassNotFoundException e) {
			logger.error("类名不存在或执行表达式错误,exception:{}", e.getMessage());
			e.printStackTrace();
		}
	}

	@Override
	public void edit(TaskInfo info) {
		String jobName = info.getTaskName(), jobGroup = info.getGroup(), cronExpression = info.getCronExpression(),
				jobDescription = info.getDesc(), createTime = LocalDateTime.now().format(formatter);
		try {
			if (!checkExists(jobName, jobGroup)) {
				logger.info("edit job fail, job is not exist, jobGroup:{}, jobName:{}", jobGroup, jobName);
			}
			TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
			JobKey jobKey = new JobKey(jobName, jobGroup);
			CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression)
					.withMisfireHandlingInstructionDoNothing();
			CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withDescription(createTime)
					.withSchedule(cronScheduleBuilder).build();

			JobDetail jobDetail = scheduler.getJobDetail(jobKey);
			jobDetail.getJobBuilder().withDescription(jobDescription);
			HashSet<Trigger> triggerSet = new HashSet<>();
			triggerSet.add(cronTrigger);

			scheduler.scheduleJob(jobDetail, triggerSet, true);
		} catch (SchedulerException e) {
			logger.error("类名不存在或执行表达式错误,exception:{}", e.getMessage());
		}

	}

	@Override
	public void delete(String jobName, String jobGroup) {
		TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
		try {
			if (checkExists(jobName, jobGroup)) {
				scheduler.pauseTrigger(triggerKey);
				scheduler.unscheduleJob(triggerKey);
				logger.info("delete job, triggerKey:{},jobGroup:{}, jobName:{}", triggerKey, jobGroup, jobName);
			}
		} catch (SchedulerException e) {
			logger.error(e.getMessage());
		}

	}

	@Override
	public void pause(String jobName, String jobGroup) {
		TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
		try {
			if (checkExists(jobName, jobGroup)) {
				scheduler.pauseTrigger(triggerKey);
				logger.info("pause job success, triggerKey:{},jobGroup:{}, jobName:{}", triggerKey, jobGroup, jobName);
			}
		} catch (SchedulerException e) {
			logger.error(e.getMessage());
		}

	}

	@Override
	public void resume(String jobName, String jobGroup) {
		TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);

		try {
			if (checkExists(jobName, jobGroup)) {
				scheduler.resumeTrigger(triggerKey);
				logger.info("resume job success,triggerKey:{},jobGroup:{}, jobName:{}", triggerKey, jobGroup, jobName);
			}
		} catch (SchedulerException e) {
			logger.error(e.getMessage());
		}

	}

	@Override
	public boolean checkExists(String jobName, String jobGroup) throws SchedulerException {
		TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
		return scheduler.checkExists(triggerKey);
	}

}
